package cn.edu.tju.core.security.rest;

import cn.edu.tju.core.model.Authority;
import cn.edu.tju.core.security.repository.AuthorityRepository;
import cn.edu.tju.core.model.Person;
import cn.edu.tju.core.security.SecurityUtils;
import cn.edu.tju.core.security.UserModelDetailsService;
import cn.edu.tju.core.security.repository.PersonRepository;
import cn.edu.tju.core.security.repository.UserRepository;
import cn.edu.tju.core.security.rest.dto.LoginDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.access.AccessDeniedException;
import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.core.security.rest.dto.UserDto;
import java.util.Set;
import java.util.HashSet;


import java.time.LocalDateTime;

@RestController
@RequestMapping("/api")
@Tag(name = "管理用户", description = "提供用户的增删改查操作")
public class UserRestController {

   private final UserService userService;
   private final PersonRepository personRepository;
//   private final UserDetailsPasswordService userDetailsPasswordService;
   private final UserModelDetailsService userModelDetailsService;
   private final UserRepository userRepository;
   private final PasswordEncoder passwordEncoder;
    private final AuthorityRepository authorityRepository;

   public UserRestController(UserService userService, PersonRepository personRepository, UserModelDetailsService userModelDetailsService, UserRepository userRepository, PasswordEncoder passwordEncoder, AuthorityRepository authorityRepository) {
      this.userService = userService;
      this.personRepository = personRepository;
      this.userModelDetailsService = userModelDetailsService;
      this.userRepository = userRepository;
      this.passwordEncoder = passwordEncoder;
      this.authorityRepository = authorityRepository;
   }

   @PostMapping("/users")
   @Operation(summary = "新增用户（仅登录帐号）", description = "创建一个新的用户（仅登录帐号）")
   public ResponseEntity<?> createUser(@RequestBody User newUser) {
      
      // 检查用户名是否已被注册
      if (newUser.getUsername() != null && 
          userRepository.findOneByUsername(newUser.getUsername()).isPresent()) {
         return ResponseEntity.status(HttpStatus.CONFLICT)
                .body("错误：用户名 '" + newUser.getUsername() + "' 已被注册！");
      }

      // 检查手机号是否已被注册
      if (newUser.getPhoneNumber() != null && 
          userRepository.findOneByPhoneNumber(newUser.getPhoneNumber()).isPresent()) {
         return ResponseEntity.status(HttpStatus.CONFLICT)
                .body("错误：手机号 '" + newUser.getPhoneNumber() + "' 已被注册！");
      }

      try {
         // 注意：这里我们使用了 newUser.getPassword() 来获取前端传来的明文密码
         newUser.setPassword(passwordEncoder.encode(newUser.getPassword()));
         
         // 设置基本属性
         newUser.setCreateTime(LocalDateTime.now());
         newUser.setUpdateTime(LocalDateTime.now());
         newUser.setCreator(null); // 公开注册时没有创建者，设为null
         newUser.setUpdater(null); // 公开注册时没有更新者，设为null
         newUser.setDeleted(false);
         newUser.setActivated(true);
   
         // 确保有默认角色（如果前端未传递）
         if (newUser.getAuthorities() == null || newUser.getAuthorities().isEmpty()) {
            Set<Authority> authorities = new HashSet<>();
            authorityRepository.findById("USER").ifPresent(authorities::add);
            newUser.setAuthorities(authorities);
         } else {
            // 验证前端传递的权限是否存在
            Set<Authority> validAuthorities = new HashSet<>();
            for (Authority auth : newUser.getAuthorities()) {
               authorityRepository.findById(auth.getName())
                  .ifPresent(validAuthorities::add);
            }
            newUser.setAuthorities(validAuthorities);
         }
   
         User savedUser = userService.addUser(newUser);
         return ResponseEntity.ok(savedUser);
      } catch (Exception e) {
         return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body("注册失败: " + e.getMessage());
      }
   }

   @GetMapping("/user")
   @Operation(summary = "判断当前登录的用户", description = "判断当前登录的用户")
   public ResponseEntity<User> getActualUser() {
      // 使用 orElseThrow 来安全地处理 Optional 容器
      User currentUser = userService.getUserWithAuthorities()
              .orElseThrow(() -> new AccessDeniedException("用户未登录或认证信息无效"));
              
      return ResponseEntity.ok(currentUser);
   }

   @PostMapping("/password")
   @Operation(summary = "修改密码", description = "已登录的用户只可以修改自己的密码，Admin可以修改任何人的密码")
   public ResponseEntity<String> updateUserPassword(@RequestBody LoginDto loginDto) {
      // 1. 安全地获取当前登录的用户信息
      // 如果用户未登录，会直接抛出异常，Spring Security 会处理为 401 或 403 错误
      User currentUser = userService.getUserWithAuthorities()
         .orElseThrow(() -> new AccessDeniedException("用户未登录，无法修改密码"));

      // 2. 安全地获取需要修改密码的目标用户信息
      // 如果目标用户不存在，会抛出异常，被全局异常处理器捕获后可以返回 404 Not Found
      User userToUpdate = userRepository.findOneWithAuthoritiesByUsername(loginDto.getUsername())
         .orElseThrow(() -> new RuntimeException("用户 '" + loginDto.getUsername() + "' 不存在"));

      // 3. 使用更简洁的方式判断当前用户是否是管理员
      boolean isAdmin = currentUser.getAuthorities().stream()
         .anyMatch(authority -> "ADMIN".equals(authority.getName()));

      // 4. 检查权限：当前用户必须是TA自己，或者是管理员
      if (currentUser.getUsername().equals(userToUpdate.getUsername()) || isAdmin) {

      // 5. 使用注入的 passwordEncoder 来加密密码，这是最佳实践
      userToUpdate.setPassword(passwordEncoder.encode(loginDto.getPassword()));

      // 6. 保存更新后的用户信息
      userRepository.save(userToUpdate);

      return ResponseEntity.ok("密码更新成功。");
      } else {
      // 7. 如果没有权限，返回 403 Forbidden 错误，这比 422 更准确
      return ResponseEntity.status(HttpStatus.FORBIDDEN).body("权限不足，无法修改他人密码。");
}
   }

   @GetMapping("/users/check")
   @Operation(summary = "检查用户名是否可用", description = "检查提供的用户名是否可用于注册")
   public ResponseEntity<?> checkUsername(@RequestParam String username) {
      // 检查用户名是否已存在
      if (userRepository.findOneByUsername(username).isPresent()) {
         return ResponseEntity.status(HttpStatus.CONFLICT).body("错误：用户名 '" + username + "' 已被注册！");
      }
      // 用户名可用
      return ResponseEntity.ok("用户名可用");
   }

   @GetMapping("/users/check-phone")
   @Operation(summary = "检查手机号是否可用", description = "检查提供的手机号是否可用于注册")
   public ResponseEntity<?> checkPhoneNumber(@RequestParam String phoneNumber) {
      // 检查手机号是否已存在
      if (userRepository.findOneByPhoneNumber(phoneNumber).isPresent()) {
         return ResponseEntity.status(HttpStatus.CONFLICT).body("错误：手机号 '" + phoneNumber + "' 已被注册！");
      }
      // 手机号可用
      return ResponseEntity.ok("手机号可用");
   }

   @PostMapping("/persons")
   @Operation(summary = "新增用户（自然人）", description = "创建一个新的用户（自然人）")
   public Person addPerson(@RequestBody Person person){
      User user = userService.getUserWithAuthorities().get();
      LocalDateTime now = LocalDateTime.now();
      person.setCreator(user.getId());
      person.setCreateTime(now);
      person.setUpdater(user.getId());
      person.setUpdateTime(now);
      person.setDeleted(false);
      person.setPassword(SecurityUtils.BCryptPasswordEncode("password"));
      person.setActivated(true);
      return personRepository.save(person);
   }

   @PostMapping("/users/{userId}/roles/business")
   @Operation(summary = "为用户添加商家角色", description = "为指定用户添加BUSINESS角色，使其可以创建商家")
   public ResponseEntity<?> addBusinessRole(@PathVariable Long userId) {
    try {
        // 获取要修改的用户
        User userToUpdate = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户ID:" + userId + " 不存在"));
            
        // 检查用户是否已有BUSINESS角色
        boolean alreadyHasBusiness = userToUpdate.getAuthorities().stream()
            .anyMatch(auth -> "BUSINESS".equals(auth.getName()));
            
        if (alreadyHasBusiness) {
            return ResponseEntity.ok("用户已拥有商家角色");
        }
        
        // 添加BUSINESS角色
        Set<Authority> authorities = new HashSet<>(userToUpdate.getAuthorities());
        authorityRepository.findById("BUSINESS")
            .ifPresent(authorities::add);
            
        userToUpdate.setAuthorities(authorities);
        userToUpdate.setUpdateTime(LocalDateTime.now());
        
        // 保存更新后的用户
        userRepository.save(userToUpdate);
        
        return ResponseEntity.ok("成功添加商家角色");
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body("添加商家角色失败: " + e.getMessage());
    }
}
}
